package thread;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;


public class ThreadDemo {

    public static void main(String[] args) {
        //new Son().father();
        //new Son().run();
        ExecutorService exec = Executors.newCachedThreadPool();
        //exec.execute(new Son());
        ArrayList<Future<String>> results = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
        results.add(exec.submit(new TaskWithResult(i)));
        }
        
        try {
            //System.out.println("result no check first: "+results.get(0).get());
            if(results.get(0).isDone()){
                System.out.println("result check: "+results.get(0).get());
            }
            System.out.println("result no check: "+results.get(0).get());
        } catch (InterruptedException ex) {
            Logger.getLogger(ThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(ThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
        } finally{
            exec.shutdown();
        }
        ExecutorService es = Executors.newCachedThreadPool(new DaemonThreadFactory());
        for (int i = 0; i < 3; i++) {
            es.execute(new Father());
        }
    }
    
}

class TaskWithResult implements Callable<String>{
    final private int id;
    public TaskWithResult(int id){
        this.id = id;
    }
    public String call(){
        try {
            TimeUnit.MILLISECONDS.sleep(5000);
        } catch (InterruptedException ex) {
            Logger.getLogger(TaskWithResult.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "result of TaskWithResult " + id;
    }
}

class Father implements Runnable{
    @Override
    public void run(){
        try {
            TimeUnit.MILLISECONDS.sleep(1000);
            System.out.println("I am father thread");
        } catch (InterruptedException ex) {
            Logger.getLogger(Father.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void father(){
        System.out.println("I am father");
    }
}

class Son extends Father{
    @Override
    public void father(){
        System.out.println("I am son");
    }
    @Override
    public void run(){
        try {
            TimeUnit.MILLISECONDS.sleep(1000);
            System.out.println("I am son thread");
        } catch (InterruptedException ex) {
            Logger.getLogger(Father.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}